package com.xli.metadata.frameconfig.service.impl;

import com.alicp.jetcache.Cache;
import com.alicp.jetcache.CacheManager;
import com.alicp.jetcache.anno.CacheConsts;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.template.QuickConfig;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xli.metadata.frameconfig.entity.ConfigCache;
import com.xli.metadata.frameconfig.entity.FrameConfig;
import com.xli.metadata.frameconfig.mapper.FrameConfigMapper;
import com.xli.metadata.frameconfig.mapper.IConfigCacheMapper;
import com.xli.metadata.frameconfig.service.IFrameConfigService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Validated
@Service
public class FrameConfigServiceImpl extends ServiceImpl<FrameConfigMapper, FrameConfig> implements IFrameConfigService {

    private final Lock lock = new ReentrantLock();

    @Autowired
    CacheManager cacheManager;

    Cache<String, ConfigCache> configCache;

    @PostConstruct
    public void init() {
        lock.lock();
        try {
            QuickConfig qc = QuickConfig.newBuilder("frame_config:entity:")
                    .expire(Duration.ofSeconds(CacheConsts.DEFAULT_EXPIRE))
                    .cacheType(CacheType.BOTH)
                    .syncLocal(true)
                    .build();
            configCache = cacheManager.getOrCreateCache(qc);

            List<FrameConfig> frameConfigList = this.list(new QueryWrapper<>());
            List<ConfigCache> configCacheList = IConfigCacheMapper.INSTANCE.toCacheList(frameConfigList);

            configCacheList.forEach(config -> {
                configCache.put(config.getConfig_name(), config);
            });
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean insert(FrameConfig frameConfig) {
        lock.lock();
        try {
            boolean result = this.save(frameConfig);
            if (result) {
                configCache.put(frameConfig.getConfig_name(), IConfigCacheMapper.INSTANCE.toCacheEntity(frameConfig));
            }
            return result;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean delete(long id) {
        lock.lock();
        try {
            FrameConfig frameConfig = this.find(id);
            if (frameConfig != null) {
                boolean result = this.removeById(frameConfig.getId());
                if (result) {
                    configCache.remove(frameConfig.getConfig_name());
                }
                return result;
            }
            return false;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean update(FrameConfig frameConfig) {
        lock.lock();
        try {
            FrameConfig config = this.find(frameConfig.getId());
            if (config != null) {
                boolean result = this.updateById(frameConfig);
                if (result) {
                    configCache.remove(config.getConfig_name());
                    configCache.put(frameConfig.getConfig_name(), IConfigCacheMapper.INSTANCE.toCacheEntity(frameConfig));
                }
                return result;
            }
            return false;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public FrameConfig find(Long id) {
        return this.getById(id);
    }

    @Override
    public Page<FrameConfig> findList(QueryWrapper<FrameConfig> qw, long current, long size) {
        return this.page(new Page<>(current, size), qw);
    }

    @Override
    public FrameConfig findConfigByName(String name) {
        ConfigCache config = configCache.get(name);
        if (config != null) {
            return IConfigCacheMapper.INSTANCE.toEntity(config);
        }
        return null;
    }
}
